<template>
  <div>
    <el-container>
      <el-aside class="tree-aside">
        <el-tree
            :props="treeProps"
            :data="treeData"
            highlight-current
            ref="tree"
            @node-click="handleNodeClick"
            @node-contextmenu="handleRightClick"
            :load="loadNode"
            lazy
            style="font-size: 16px"
        >
          <template #default="{ node, data }">
            <span class="custom-tree-node">
              <span class="node-item">
                <img :src="selectIcon(data)" alt="">
                <span>{{ node.label }}</span>
              </span>
            </span>
          </template>
        </el-tree>
        <div id="tree-menu"
             class="tree-menu"
             v-show="menuDialogVis"
             :style="`left: ${clientX}px; top: ${clientY}px; font-size: 14px`"
        >
          <el-menu
              id="rightClickMenu"
              class="el-menu-vertical tree-sub-menu"
              @select="handleRightSelect"
          >
            <!--TODO 选项数据结构定义 1、目前无法针对文件夹/文件个性化显示 2、自定义属性确定选择了哪一个选项，弹出对应的操作弹框-->
            <el-menu-item :key="item.type" v-for="item in menuOption" :index="item.type" class="menuItem">
              <span slot="title">{{ item.text }}</span>
            </el-menu-item>
          </el-menu>
        </div>
      </el-aside>
      <el-main>
        <div id="parent-doc" class="doc-container">
          <div class="doc-container" id="doc-container"></div>
        </div>
      </el-main>
    </el-container>
    <!--文件类型dialog-->
    <el-dialog
        title="提示"
        v-model="docsTypeDialogVis"
        width="30%">
      <span>目前云文档组件仅支持 doc 类型</span>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="docsTypeDialogVis = false">确 定</el-button>
        </span>
      </template>
    </el-dialog>
    <!--  上传文件 dialog-->
    <el-dialog title="单个文件不得超过20M，最大文件数量为5" v-model="uploadDialogVis" width="30%" center>
      <el-upload
          drag
          :action="uploadApi"
          :limit="10"
          multiple
          ref="filesUpload"
          :http-request="submitUpload"
          :on-exceed="onFileExceeded"
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <template #tip>
          <div class="el-upload__tip">该功能基于接口<em><a
              href="https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/drive-v1/file/upload_all"
              target="_blank">上传文件</a></em>实现，具体约束详见文档。
          </div>
        </template>
      </el-upload>
      <div>
        <el-button
            style="margin-left: 10px;"
            size="small"
            type="success"
        >上传到服务器
        </el-button>
        <el-popconfirm
            confirmButtonText="好的"
            cancelButtonText="不用了"
            icon="el-icon-info"
            iconColor="red"
            title="确定清空全部文件吗？"
            @confirm="clearFilesUpload"
        >
          <template #reference>
            <el-button type="danger" size="small">清空文件列表</el-button>
          </template>
        </el-popconfirm>
      </div>
    </el-dialog>
    <!--新建文件夹dialog-->
    <el-dialog title="新建文件夹" v-model="createFolderDialog">
      <el-form :model="createFolderForm">
        <el-form-item label="文件夹标题">
          <el-input v-model="createFolderForm.title" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="createFolderDialog = false">取 消</el-button>
          <el-button type="primary" @click="onCreateFolderSubmit">确 定</el-button>
        </span>
      </template>
    </el-dialog>
    <!--删除文档dialog-->
    <el-dialog
        title="提示"
        v-model="delDocDialog"
        width="30%"
    >
      <span>这将会同步飞书云文档的文档，确认删除吗？</span>
      <template #footer>
    <span class="dialog-footer">
      <el-button @click="delDocDialog = false">取 消</el-button>
      <el-button type="primary" @click="onDelDocSubmit">确 定</el-button>
    </span>
      </template>
    </el-dialog>
    <!--删除 sheet dialog-->
    <el-dialog
        title="提示"
        v-model="delSheetDialog"
        width="30%"
    >
      <span>这将会同步飞书云文档的文档，确认删除吗？</span>
      <template #footer>
    <span class="dialog-footer">
      <el-button @click="delSheetDialog = false">取 消</el-button>
      <el-button type="primary" @click="onDelSheetSubmit">确 定</el-button>
    </span>
      </template>
    </el-dialog>
    <!--新建文件夹dialog-->
    <el-dialog title="新建电子表格" v-model="createSheetDialog">
      <el-form :model="createSheetForm">
        <el-form-item label="电子表格标题">
          <el-input v-model="createSheetForm.title" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="createSheetDialog = false">取 消</el-button>
          <el-button type="primary" @click="onCreateSheetSubmit">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import {folderChildren, rootFolder, uploadAll, createFolder} from '@/api/docs/explorer';
import {createDoc, delDoc, docMeta} from '@/api/docs/doc';
import {docSDK} from '@/api/auth/auth';
import lark from '@/config';
import {createSheet, delSheet} from '@/api/docs/sheet';

export default {
  name: 'docsTree',
  data() {
    return {
      treeProps: {
        label: 'name',
        children: 'children',
        auth_token: 'auth_token',
        type: 'type',
        isLeaf: 'leaf',
      },
      clientX: '',
      clientY: '',
      menuDialogVis: false,
      menuOption: [],
      treeData: [],
      docsTypeDialogVis: false,
      docIcon: require('@/assets/icon/doc.png'),
      sheetIcon: require('@/assets/icon/sheet.png'),
      fileIcon: require('@/assets/icon/file.png'),
      folderIcon: require('@/assets/icon/folder.png'),
      // upload file all
      uploadDialogVis: false,
      uploadApi: lark.env.api.DOCS.DRIVE.V1_FILES_UPLOAD_ALL,
      uploadFolderToken: '',
      nodeWasSelected: null, // 右键时选中的节点（文件夹/文件）
      // create folder
      createFolderDialog: false,
      createFolderForm: {
        title: '',
      },
      // del doc
      delDocDialog: false,
      // del sheet
      delSheetDialog: false,
      // create sheet
      createSheetDialog: false,
      createSheetForm: {
        title: '',
      },
    };
  },
  methods: {
    handleRightClick(event, data, node, vComponent) {
      this.menuDialogVis = true;
      const {target} = event;
      // 经验值
      this.clientX = target.offsetLeft + 100;
      this.clientY = target.offsetTop + 20;
      const {leaf, type, token} = data;
      if (leaf) {
        const ops = [];
        if (type === 'doc') {
          ops.push({
            text: '删除Doc',
            type: 'del_doc',
          });
        } else if (type === 'sheet') {
          ops.push({
            text: '删除Sheet',
            type: 'del_sheet',
          });
        }
        this.menuOption = ops;
      } else {
        this.uploadFolderToken = token;
        this.nodeWasSelected = node;
        this.menuOption = [
          {text: '新建文件夹', type: 'create_folder'},
          {text: '上传文件', type: 'upload_file'},
          {text: '新建文档(doc)', type: 'create_doc'},
          {text: '新建表格(sheet)', type: 'create_sheet'},
        ];
      }
      // console.log(data, target, node);
      this.nodeWasSelected = node;
    },
    onUploadFile() {
      this.uploadDialogVis = true;
    },
    onCreateFolder() {
      this.createFolderDialog = true;
    },
    onDelDoc() {
      this.delDocDialog = true;
    },
    onDelSheet() {
      this.delSheetDialog = true;
    },
    async onCreateDoc() {
      const {token} = this.nodeWasSelected.data;
      const {type} = this.$route.query;
      const createRes = await createDoc({
        folderToken: token,
        type,
      });
      const {data} = createRes;
      if (data.code !== 0) {
        this.$message.error('网络失联～');
        return;
      }
      console.log(data);
      this.$message.success('创建成功, 已为您打开文档');
      this.freeAndRefreshCurNode();
      await this.loadDocComponent(data.data.url);
    },
    async onCreateSheet() {
      this.createSheetDialog = true;
    },
    handleRightSelect(key) {
      console.log(key);
      this.menuDialogVis = false;
      switch (key) {
        case 'upload_file':
          this.onUploadFile();
          break;
        case 'create_folder':
          this.onCreateFolder();
          break;
        case 'del_doc':
          this.onDelDoc();
          break;
        case 'del_sheet':
          this.onDelSheet();
          break;
        case 'create_doc':
          this.onCreateDoc();
          break;
        case 'create_sheet':
          this.onCreateSheet();
          break;
      }
    },
    async handleNodeClick(data, node) {
      this.menuDialogVis = false;
      if (data.type !== 'folder') {
        const {type} = this.$route.query;
        console.log('file');
        // 文件就获取元信息，在右边栏展示出来
        if (data.type === 'sheet') {
          // sheet
          this.docsTypeDialogVis = true;
        } else if (data.type === 'doc') {
          // doc
          const metaRes = await docMeta({docToken: data.token, type});
          const metaData = metaRes.data;
          if (metaData.code !== 0) {
            this.$message.error(metaData.msg);
          }
          await this.loadDocComponent(metaData.data.url);
        } else {
          // file
          this.docsTypeDialogVis = true;
        }
      }
    },
    selectIcon(data) {
      switch (data.type) {
        case 'doc':
          return this.docIcon;
        case 'sheet':
          return this.sheetIcon;
        case 'folder':
          return this.folderIcon;
      }
      return this.fileIcon;
    },
    async getRootFolder() {
      const {type} = this.$route.query;
      return await rootFolder({type});
    },
    async loadDocComponent(doc_url) {
      console.log(doc_url);
      const parentNode = document.querySelector('#parent-doc');
      parentNode.innerHTML = '<div  id="doc-container"></div>';
      const {type} = this.$route.query;
      const content = await docSDK({type});
      console.log(content);
      const {data} = content;
      if (data.code !== 0) {
        this.$message.error('鉴权失败，请重新提交身份信息！');
        return;
      }
      const {appId, timestamp, nonceStr, signature, url, lang, openId} = data.data;
      const jsApiList = ['DocsComponent'];
      window.webComponent.config({
        openId,
        signature, // 签名
        appId, // 应用 appId
        timestamp, // 时间戳（毫秒）
        nonceStr, // 随机字符串
        url, // app URL
        jsApiList, // 指定要使用的组件，如 ['DocsComponent']
        lang, // 指定组件的国际化语言：en-英文、zh-中文、ja-日文
      })
          .then((_) => {
            // 可以在这里进行组件动态渲染;
            // 先删除原节点;
            const docComponentInstance = window.webComponent.render(
                'DocsComponent',
                {
                  src: doc_url,
                  minHeight: '100%',
                  width: '100%',
                },
                document.querySelector('#doc-container'),
            );
            docComponentInstance.config.setFeatureConfig({
              FULLSCREEN: {
                enable: true,
              },
              SIDEBAR: {
                enable: [false, false, false, false],
              },
              SHARE: {
                enable: true,
                visibleConfig: {
                  invite: true,
                  shareLink: true,
                  shareMethod: true,
                },
              },
              HEADER: {
                enable: true,
              },
              CONTENT: {
                mode: 'default',
                readonly: false,
              },
              COLLABORATOR: {
                enable: true,
              },
              DIRECTORY: {
                enable: true,
                pin: true,
              },
              MORE_MENU: {
                enable: true,
                items: {
                  findAndReplaceEnable: true,
                  makeCopyEnable: true,
                  applyEditPermissionEnable: true,
                  exportEnable: true,
                  documentInfoEnable: true,
                  editHistoryEnable: true,
                  commentHistoryEnable: true,
                  translateEnable: true,
                  printEnable: true,
                  deleteEnable: true,
                },
              },
            });
          });
      // 捕获组件内部错误
      window.webComponent.onError(function(error) {
        console.error('custom error:', error);
      });
      window.webComponent.onAuthError(function(error) {
        console.error('auth error callback', error);
      });
    },
    async loadNode(node, resolve) {
      if (node.level === 0) {
        const {data} = await this.getRootFolder();
        return resolve([data.data]);
      }
      const {data} = node;
      if (data.type === 'folder') {
        // 文件夹就加载子节点
        const folderToken = data.token;
        const {type} = this.$route.query;
        const folderChildrenRes = await folderChildren({folderToken, type});
        if (folderChildrenRes.data.code !== 0) {
          this.$message.error(folderChildrenRes.data.msg);
          return;
        }
        setTimeout(() => {
          resolve(folderChildrenRes.data.data);
        }, 250);
      }
    },
    //  各种 dialog 逻辑
    freeAndRefreshCurNode() {
      // 当节点为文件夹时，直接刷新
      this.nodeWasSelected.loaded = false;
      this.nodeWasSelected.expand();
      this.nodeWasSelected = null;
    },
    freeAndRefreshParentNode() {
      // 当节点为文件时，刷新父节点
      const parent = this.nodeWasSelected.parent;
      parent.loaded = false;
      parent.expand();
      this.nodeWasSelected = null;
    },
    async submitUpload(val) {
      const formData = new FormData();
      formData.append('file', val.file);
      formData.append('parent_node', this.uploadFolderToken);
      const {type} = this.$route.query;
      const uploadRes = await uploadAll({formData, type});
      if (uploadRes.data.code !== 0) {
        this.$message.error('上传失败，请重新尝试上传');
        return;
      }
      this.$message.success('成功上传');
      // 刷新选中 「上传文件」的节点
      this.freeAndRefreshCurNode();
    },
    clearFilesUpload() {
      this.$refs.filesUpload.clearFiles();
    },
    onFileExceeded() {
      this.clearFilesUpload();
      this.$message.warning('文件列表超出限制，已为您清除文件列表');
    },
    async onCreateFolderSubmit() {
      const {token} = this.nodeWasSelected.data;
      const {type} = this.$route.query;
      const createRes = await createFolder({
        folderToken: token,
        title: this.createFolderForm.title,
        type,
      });
      this.createFolderForm.title = '';
      const {data} = createRes;
      console.log(data);
      if (data.code !== 0) {
        this.createFolderDialog = false;
        return;
      }
      this.createFolderDialog = false;
      this.freeAndRefreshCurNode();
      this.$message.success('文件夹创建成功');
    },
    async onDelDocSubmit() {
      const {token} = this.nodeWasSelected.data;
      const {type} = this.$route.query;
      const delDocRes = await delDoc({
        docToken: token,
        type,
      });
      const {data} = delDocRes;
      if (data.code !== 0) {
        this.$message.error('网络失联～');
        return;
      }
      this.$message.success('成功删除');
      this.freeAndRefreshParentNode();
      await this.loadDocComponent('');
      this.delDocDialog = false;
    },
    async onDelSheetSubmit() {
      const {token} = this.nodeWasSelected.data;
      const {type} = this.$route.query;
      const delDocRes = await delSheet({
        sheetToken: token,
        type,
      });
      const {data} = delDocRes;
      if (data.code !== 0) {
        this.$message.error('网络失联～');
        return;
      }
      this.$message.success('成功删除');
      this.freeAndRefreshParentNode();
      this.delSheetDialog = false;
    },
    async onCreateSheetSubmit() {
      const {token} = this.nodeWasSelected.data;
      const {type} = this.$route.query;
      const createRes = await createSheet({
        folderToken: token,
        title: this.createSheetForm.title,
        type,
      });
      this.createSheetForm.title = '';
      const {data} = createRes;
      if (data.code !== 0) {
        this.$message.error('网络失联～');
        return;
      }
      console.log(data);
      this.$message.success('创建成功, 云文档组件目前仅支持 DOC 类型，暂时无法打开');
      this.freeAndRefreshCurNode();
      this.createSheetDialog = false;
    },
  },
};
</script>

<style>
.tree-aside {
  position: relative;
  white-space: nowrap;
  width: 288px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  text-align: justify;
}

.node-item {
  display: inline-flex;
  justify-content: space-between;
  align-items: center;
}

.node-item > img {
  height: 16px;
  width: 16px;
  margin: 0 2px;
}

.doc-container {
  box-shadow: 0 6px 24px rgb(31, 35, 41);
  border-radius: 0 0 3px 3px;
  overflow: auto;
  height: 600px;
}

.tree-menu {
  position: absolute;
  z-index: 100000;
}

.tree-menu .tree-sub-menu {
  position: absolute;
  background-color: #fff3f3;
}

/**
改写 dialog 内容剧中
 */
.el-dialog .el-dialog__body {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}

.el-upload__tip {
  font-size: 16px;
}
</style>
